From: Raphael Bosshard Date: Thu, 27 May 2010 07:31:46 +0000 (+0200) Subject: Add ISO week dates to the calendar X-Git-Tag: archive/raspbian/50.5-1+rpi1~1^2~1013^2^2~10013 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/%22/%22http:/www.example.com/cgi/%22?a=commitdiff_plain;h=e3eaa699481b9b48e12f2d5a10baab3aed9f8acf;p=gnome-shell.git Add ISO week dates to the calendar This patch adds ISO week dates to the calendar. Week dates are an often used feature in business and government offices. Can be turned on through gconf, off by default. https://bugzilla.gnome.org/show_bug.cgi?id=603532 --- diff --git a/data/gnome-shell.schemas b/data/gnome-shell.schemas index 8e5c91f7f..434986fa5 100644 --- a/data/gnome-shell.schemas +++ b/data/gnome-shell.schemas @@ -438,6 +438,20 @@ + + + /schemas/desktop/gnome/shell/calendar/show_weekdate + /desktop/gnome/shell/calendar/show_weekdate + gnome-shell + bool + false + + Show the week date in the calendar + + If true, display the ISO week date in the calendar. + + + diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css index bee6c9fee..c34ae630d 100644 --- a/data/theme/gnome-shell.css +++ b/data/theme/gnome-shell.css @@ -899,6 +899,10 @@ StTooltip { padding: 0px 4px 2px 0px; } +.calendar-calendarweek { + color: #666666; +} + /* App Switcher */ #altTabPopup { padding: 8px; diff --git a/js/ui/calendar.js b/js/ui/calendar.js index 8122e506f..080ab1ded 100644 --- a/js/ui/calendar.js +++ b/js/ui/calendar.js @@ -3,10 +3,14 @@ const Clutter = imports.gi.Clutter; const Lang = imports.lang; const St = imports.gi.St; - +const Pango = imports.gi.Pango; +const Shell = imports.gi.Shell; const Gettext_gtk20 = imports.gettext.domain('gtk20'); const MSECS_IN_DAY = 24 * 60 * 60 * 1000; +const MSECS_IN_WEEK = MSECS_IN_DAY * 7; +const WEEKDATE_HEADER_WIDTH_DIGITS = 3; +const SHOW_WEEKDATE_KEY = 'calendar/show_weekdate'; function _sameDay(dateA, dateB) { return (dateA.getDate() == dateB.getDate() && @@ -14,6 +18,24 @@ function _sameDay(dateA, dateB) { dateA.getYear() == dateB.getYear()); } +function _getCalendarWeekForDate(date) { + let startOfYear = new Date(date.getFullYear(), 0, 1); + let sday = startOfYear.getDay(); + let offset = 4 + (7 * Math.floor(sday * (1/5))) - sday; + let firstThursday = new Date(date.getFullYear(), 0, 1 + offset); + let weekOfYear = Math.ceil((date.getTime() - firstThursday.getTime()) / MSECS_IN_WEEK); + return weekOfYear; +} + +function _getDigitWidth(actor){ + let context = actor.get_pango_context(); + let themeNode = actor.get_theme_node(); + let font = themeNode.get_font(); + let metrics = context.get_metrics(font, context.get_language()); + let width = metrics.get_approximate_digit_width(); + return width; +} + function Calendar() { this._init(); } @@ -24,6 +46,13 @@ Calendar.prototype = { // GTK+ by preference uses nl_langinfo (NL_TIME_FIRST_WEEKDAY). We probably // should add a C function so we can do the full handling. this._weekStart = NaN; + this._weekdate = NaN; + this._digitWidth = NaN; + this._gconf = Shell.GConf.get_default(); + + this._gconf.connect('changed', Lang.bind(this, this._onSettingsChange)); + this._useWeekdate = this._gconf.get_boolean(SHOW_WEEKDATE_KEY); + let weekStartString = Gettext_gtk20.gettext('calendar:week_start:0'); if (weekStartString.indexOf('calendar:week_start:') == 0) { this._weekStart = parseInt(weekStartString.substring(20)); @@ -58,11 +87,28 @@ Calendar.prototype = { this.actor.connect('scroll-event', Lang.bind(this, this._onScroll)); + this._buildHeader (); + this._update(); + }, + + // Sets the calendar to show a specific date + setDate: function(date) { + if (!_sameDay(date, this.date)) { + this.date = date; + this._update(); + } + }, + + _buildHeader: function() { + let offsetCols = this._useWeekdate ? 1 : 0; + this.actor.destroy_children(); + // Top line of the calendar '<| September 2009 |>' this._topBox = new St.BoxLayout(); this.actor.add(this._topBox, - { row: 0, col: 0, col_span: 7 }); + { row: 0, col: 0, col_span: offsetCols + 7 }); + this.actor.connect('style-changed', Lang.bind(this, this._onStyleChange)); let [backlabel, forwardlabel] = ['<', '>']; if (St.Widget.get_default_direction () == St.TextDirection.RTL) { [backlabel, forwardlabel] = [forwardlabel, backlabel]; @@ -85,25 +131,39 @@ Calendar.prototype = { let iter = new Date(this.date); iter.setSeconds(0); // Leap second protection. Hah! iter.setHours(12); + + if (this._useWeekdate) { + this._weekdateHeader = new St.Label(); + this.actor.add(this._weekdateHeader, + { row: 1, + col: 0, + x_fill: false, x_align: St.Align.MIDDLE }); + this._setWeekdateHeaderWidth(); + } else { + this._weekdateHeader = null; + } + for (let i = 0; i < 7; i++) { this.actor.add(new St.Label({ text: iter.toLocaleFormat('%a') }), { row: 1, - col: (7 + iter.getDay() - this._weekStart) % 7, + col: offsetCols + (7 + iter.getDay() - this._weekStart) % 7, x_fill: false, x_align: St.Align.END }); iter.setTime(iter.getTime() + MSECS_IN_DAY); } // All the children after this are days, and get removed when we update the calendar this._firstDayIndex = this.actor.get_children().length; + }, - this._update(); + _onStyleChange: function(actor, event) { + // width of a digit in pango units + this._digitWidth = _getDigitWidth(this.actor) / Pango.SCALE; + this._setWeekdateHeaderWidth(); }, - // Sets the calendar to show a specific date - setDate: function(date) { - if (!_sameDay(date, this.date)) { - this.date = date; - this._update(); + _setWeekdateHeaderWidth: function() { + if (this.digitWidth != NaN && this._useWeekdate && this._weekdateHeader) { + this._weekdateHeader.set_width (this._digitWidth * WEEKDATE_HEADER_WIDTH_DIGITS); } }, @@ -140,6 +200,12 @@ Calendar.prototype = { this._update(); }, + _onSettingsChange: function() { + this._useWeekdate = this._gconf.get_boolean(SHOW_WEEKDATE_KEY); + this._buildHeader(); + this._update(); + }, + _update: function() { this._dateLabel.text = this.date.toLocaleFormat(this._headerFormat); @@ -166,10 +232,20 @@ Calendar.prototype = { label.style_class = 'calendar-day calendar-other-month-day'; else label.style_class = 'calendar-day'; + + let offsetCols = this._useWeekdate ? 1 : 0; this.actor.add(label, - { row: row, col: (7 + iter.getDay() - this._weekStart) % 7, + { row: row, col: offsetCols + (7 + iter.getDay() - this._weekStart) % 7, x_fill: false, x_align: St.Align.END }); + if (this._useWeekdate && iter.getDay() == 4) { + let label = new St.Label({ text: _getCalendarWeekForDate(iter).toString(), + style_class: 'calendar-day calendar-calendarweek'}); + this.actor.add(label, + { row: row, col: 0, + x_fill: false, x_align: St.Align.MIDDLE }); + } + iter.setTime(iter.getTime() + MSECS_IN_DAY); if (iter.getDay() == this._weekStart) { // We stop on the first "first day of the week" after the month we are displaying diff --git a/js/ui/panel.js b/js/ui/panel.js index 58e1d5f3c..0a6a484fe 100644 --- a/js/ui/panel.js +++ b/js/ui/panel.js @@ -1268,6 +1268,7 @@ CalendarPopup.prototype = { Main.chrome.addActor(this.actor, { visibleInOverview: true, affectsStruts: false }); this.actor.y = (panelActor.y + panelActor.height - this.actor.height); + this.calendar.actor.connect('notify::width', Lang.bind(this, this._centerPopup)); }, show: function() { @@ -1276,7 +1277,7 @@ CalendarPopup.prototype = { // Reset the calendar to today's date this.calendar.setDate(new Date()); - this.actor.x = Math.round(panelActor.x + (panelActor.width - this.actor.width) / 2); + this._centerPopup(); this.actor.lower(panelActor); this.actor.show(); Tweener.addTween(this.actor, @@ -1296,5 +1297,10 @@ CalendarPopup.prototype = { onComplete: function() { this.actor.hide(); }, onCompleteScope: this }); + }, + + _centerPopup: function() { + let panelActor = Main.panel.actor; + this.actor.x = Math.round(panelActor.x + (panelActor.width - this.actor.width) / 2); } };